//+------------------------------------------------------------------+
//|                                                    MA ribbon.mq4 |
//|                                               mladenfx@gmail.com |
//|                                                                  |
//| original idea by Jose Silva                                      |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 C'97,48,48'  /////C'217,240,242'   //C'215,255,225'
#property indicator_color2 C'36,62,62'             ///C'240,235,183'    ///OldLace   //Gainsboro
#property indicator_color3 Teal
#property indicator_color4 Chocolate
#property indicator_width1  3
#property indicator_width2  3
#property indicator_width3  2
#property indicator_width4  2

//
//
//
//
//

extern string TimeFrame = "Current time frame";
extern int    MA1Period = 199;
extern int    MA1Method = MODE_EMA;
extern int    MA1Price  = 6;
extern int    MA1Shift  = 1;
extern int    MA2Period = 66;
extern int    MA2Method = MODE_EMA;
extern int    MA2Price  = 6;
extern int    MA2Shift  = 1;
extern int    FillWidth = 9;

//
//
//
//
//

double buffer1[];
double buffer2[];
double buffer3[];
double buffer4[];

//
//
//
//
//

string indicatorFileName;
bool   calculateValue;
bool   returnBars;
int    timeFrame;

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   SetIndexBuffer(0,buffer3); SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,FillWidth);
   SetIndexBuffer(1,buffer4); SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,FillWidth);
   SetIndexBuffer(2,buffer1); 
   SetIndexBuffer(3,buffer2); 
      
      //
      //
      //
      //
      //
      
      MA1Method         = MathMin(MathMax(MA1Method,0),4);
      MA2Method         = MathMin(MathMax(MA2Method,0),4);
      indicatorFileName = WindowExpertName();
      calculateValue    = (TimeFrame=="calculateValue"); if (calculateValue) return(0);
      returnBars        = (TimeFrame=="returnBars");     if (returnBars)     return(0);
      timeFrame         = stringToTimeFrame(TimeFrame);  
      SetIndexShift(0,MA1Shift * timeFrame/Period());  
      SetIndexShift(1,MA2Shift * timeFrame/Period()); 
      SetIndexShift(2,MA1Shift * timeFrame/Period());  
      SetIndexShift(3,MA2Shift * timeFrame/Period()); 
      
      //
      //
      //
      //
      //
      
      IndicatorShortName(timeFrameToString(timeFrame)+" MA Ribbon filled"); 
return(0);
}
int deinit()
{
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
   int i,limit;
   
   
   if(counted_bars < 0) return(-1);
   if(counted_bars > 0) counted_bars--;
           limit = MathMin(Bars-counted_bars,Bars-1); 
           if (returnBars) { buffer3[0] = limit+1; return(0); }

   //
   //
   //
   //
   //

   if (calculateValue || timeFrame == Period())
   {
     for(i=limit; i>=0; i--)
     {
        if (MA1Method<4) 
              buffer1[i] = iMA(NULL,0,MA1Period,MA1Shift,MA1Method,MA1Price,i);
        else  buffer1[i] = iLsma(iMA(NULL,0,1,MA1Shift,MODE_SMA,MA1Price,i),MA1Period,i,0);
        if (MA2Method<4) 
              buffer2[i] = iMA(NULL,0,MA2Period,MA2Shift,MA2Method,MA2Price,i);
        else  buffer2[i] = iLsma(iMA(NULL,0,1,MA2Shift,MODE_SMA,MA2Price,i),MA2Period,i,1);
        buffer3[i] = buffer1[i];
        buffer4[i] = buffer2[i];
     }
   return(0);
   }
   
   //
   //
   //
   //
   //
   
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,timeFrame,indicatorFileName,"returnBars",0,0)*timeFrame/Period()));
   for(i=limit; i>=0; i--)
   {
      int y = iBarShift(NULL,timeFrame,Time[i]);
         buffer3[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",MA1Period,MA1Method,MA1Price,MA1Shift,MA2Period,MA2Method,MA2Price,MA2Shift,0,y);
         buffer4[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",MA1Period,MA1Method,MA1Price,MA1Shift,MA2Period,MA2Method,MA2Price,MA2Shift,1,y);
         buffer1[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",MA1Period,MA1Method,MA1Price,MA1Shift,MA2Period,MA2Method,MA2Price,MA2Shift,2,y);
         buffer2[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",MA1Period,MA1Method,MA1Price,MA1Shift,MA2Period,MA2Method,MA2Price,MA2Shift,3,y);         
   }
return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workLsma[][2];
double iLsma(double price, double period, int r, int instanceNo=0)
{
   if (ArrayRange(workLsma,0)!= Bars) ArrayResize(workLsma,Bars); r = Bars-r-1;

   //
   //
   //
   //
   //
   
      period = MathMax(period,1);
      workLsma[r][instanceNo] = price;
         double lwmw = period; double lwma = lwmw*price;
         double sma  = price;
         for(int k=1; k<period && (r-k)>=0; k++)
         {
            double weight = period-k;
                   lwmw  += weight;
                   lwma  += weight*workLsma[r-k][instanceNo];  
                   sma   +=        workLsma[r-k][instanceNo];
         }             
   
   return(3.0*lwma/lwmw-2.0*sma/period);
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = stringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}

//
//
//
//
//

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

string stringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int tchar = StringGetChar(s, length);
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                     s = StringSetChar(s, length, tchar - 32);
         else if(tchar > -33 && tchar < 0)
                     s = StringSetChar(s, length, tchar + 224);
   }
   return(s);
}




